import koaRouter from 'koa-router'
import axios from 'axios'
import bcrypt from 'bcryptjs'
import { signToken } from '@/utils/token'
import { successRes, errorRes, codeEnum } from '@/utils/responseModel'
import { sendMail, verificationCode } from '@/utils/sendEmail'
import { bodyNotNull, State } from '@/utils/utils'
import { Context } from 'koa'
import { dataSource } from '@/utils/typeormConnect'
import { User } from '@/model/User'

const userRepository = dataSource.getRepository(User)

const router = new koaRouter()

router.prefix('/public')

const getWeOpenId = (wxCode: string) => {
    return new Promise((resolve) => {
        axios.post('https://api.weixin.qq.com/sns/jscode2session', {
            js_code: wxCode,
            appid: 'wxc6b434543d49d2bb', // 仅为实例appid
            secret: 'c6cc529d225363aa5537f2dbfc631166', // 仅为实例secret
            grant_type: 'authorization_code'
        }, {
            headers: {
                'content-type': 'application/x-www-form-urlencoded'
            }
        }).then(r => {
            resolve(r)
        })
    })
}

const isRegister = (ctx: Context) => {
    const body = ctx.request.body as Record<string, any>
    switch (body.env) {
    case 'weapp':
        bodyNotNull(ctx, ['wxOpenId'])
        return userRepository.
            createQueryBuilder()
            .select()
            .where((qb) => {
                qb.where('wxOpenId = :wxOpenId', { wxOpenId: body.wxOpenId })
                    .andWhere('state = 1')
            }).getOne()
    case 'h5':
        bodyNotNull(ctx, ['email'])
        return userRepository.
            createQueryBuilder()
            .select()
            .where((qb) => {
                qb.where('email = :email', { email: body.email })
                    .andWhere('state = 1')
            }).getOne()
    default:
        return Promise.reject()
    }
}

router.post('/login', async (ctx) => {
    const body = ctx.request.body as {
        wxCode: string,
        wxOpenId: string
        email: string,
        password: string,
        env: string
    }
    const { wxCode, password, env } = body
    if (env === 'weapp') {
        await getWeOpenId(wxCode).then(async (r: any) => {
            body.wxOpenId = r.data.openid
        })
    }

    await isRegister(ctx).then(async r => {
        if (!r) throw new errorRes('账号未注册', codeEnum.unRegistered)
        switch (env) {
        case 'weapp':
            ctx.body = new successRes({ token: await signToken({ userId: r.id!, time: new Date().getTime(), ip: ctx.ip }) })
            break
        case 'h5':
            if (r) {
                if (!bcrypt.compareSync(password, r.password!)) throw new errorRes('密码错误')
                ctx.body = new successRes({ token: await signToken({ userId: r.id!, time: new Date().getTime(), ip: ctx.ip }) })
            }
            break
        default:
            break
        }
    })
})

router.post('/register', async (ctx) => {
    const body = ctx.request.body as {
        env: string,
        wxCode: string,
        wxOpenId: string,
        email: string,
        verificationCode: string,
        name: string,
        password: string
    }

    if (body.env === 'weapp') {
        await getWeOpenId(body.wxCode).then(async (r: any) => {
            body.wxOpenId = r.data.openid
        })
    }

    await isRegister(ctx).then(async r => {
        if (r) throw new errorRes('该账号已注册', codeEnum.registered)
        switch (body.env) {
        case 'weapp':
            bodyNotNull(ctx, ['wxOpenId'])
            return await userRepository.save(new User({ wxOpenId: body.wxOpenId, name: body.name }))
        case 'h5':
            bodyNotNull(ctx, ['email', 'password', 'verificationCode'])
            if (verificationCode(body.email, body.verificationCode) === State.unavailable) throw new errorRes('验证码错误')
            return await userRepository.save(new User({
                email: body.email,
                password: bcrypt.hashSync('123456', bcrypt.genSaltSync(10)),
                name: body.name
            }))
        default:
            break
        }
    }).then(async r => {
        if (!r) throw new errorRes('注册失败')
        ctx.body = new successRes({ token: await signToken({ userId: r.id!, time: new Date().getTime(), ip: ctx.ip }) }, '注册成功')
    })
})

router.post('/getVerificationCode', async (ctx) => {
    const { email } = ctx.request.body as { email: string }
    bodyNotNull(ctx, ['email'])
    await isRegister(ctx).then(async r => {
        if (r) throw new errorRes('该账号已注册', codeEnum.registered)
        return sendMail(email)
    }).then(() => {
        ctx.body = new successRes({}, '验证码发送成功')
    })
})

export default router